package lacus.wd_cinema.service;

import lacus.wd_cinema.dto.users.UserCreateRequest;
import lacus.wd_cinema.dto.users.UserCreateResponse;
import lacus.wd_cinema.dto.users.UserUpdateRequest;
import lacus.wd_cinema.entity.User;
import lacus.wd_cinema.exception.EntityNotFoundException;
import lacus.wd_cinema.exception.OperationNotAllowedException;
import lacus.wd_cinema.exception.ValidationException;
import lacus.wd_cinema.repository.UserRepository;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;

/**
 * 与用户相关的业务处理类
 * @author lacus
 * @version 0.5
 * @since 0.1
 */
@Service
@Transactional
public class UserService {
    public final UserRepository userRepository;
    public static final String DEFAULT_PASSWORD = "123456";
    private final LogService logService;

    public UserService(UserRepository userRepository, LogService logService) {
        this.userRepository = userRepository;
        this.logService = logService;
    }

    /**
     * 根据ID获取用户
     * @param id 用户ID
     * @return 用户
     */
    public User getUserById(long id) {
        return userRepository.findById(id).orElseThrow(
                () -> new EntityNotFoundException("未知的ID为" + id + "的用户")
        );
    }

    /** 创建新的用户 */
    public UserCreateResponse createUser(UserCreateRequest request, User operator) {
        User user = new User();
        BeanUtils.copyProperties(request, user);
        if (userRepository.existsByUsername(user.getUsername())) {
            throw new ValidationException("用户名已经存在");
        }
        user.setCreatedAt(LocalDate.now());
        User savedUser = userRepository.save(user);
        logService.log(operator, "创建了%s： (ID=%d)'%s'".formatted(
                savedUser.getRole().getDisplayName(),
                savedUser.getId(), savedUser.getUsername())); // 记录业务日志
        return UserCreateResponse.from(savedUser);
    }

    /** 更新已有用户的信息 */
    public void updateUser(long id, UserUpdateRequest request, User operator) {
        User user = getUserById(id);
        if (user.isAdmin()) {
            throw new OperationNotAllowedException("不允许对管理员用户进行修改");
        }
        BeanUtils.copyProperties(request, user);
        logService.log(operator, "修改了%s: (ID=%d)'%s'".formatted(
                user.getRole().getDisplayName(), user.getId(),user.getUsername()
        ));
        userRepository.save(user);
    }

    /** 重置用户的密码 */
    public void resetPassword(long id, User operator) {
        User user = getUserById(id);
        user.setPassword(DEFAULT_PASSWORD);
        userRepository.save(user);
        logService.log(operator, "重置了%s: (ID=%d)'%s'的密码"
                .formatted(user.getRole().getDisplayName(),
                        user.getId(),user.getUsername())); // 记录业务日志
    }

    /** 删除已有用户 */
    public void deleteUser(long id, User operator) {
        User user = getUserById(id);
        if (user.getUsername().equals("admin")) {
            throw new OperationNotAllowedException("不允许删除admin管理员");
        }
        userRepository.deleteById(id);
        logService.log(operator, "删除了%s: (ID=%d)'%s'".formatted(
                user.getRole().getDisplayName(), user.getId(),user.getUsername()
        ));
    }

    /**
     * 查询所有用户列表
     * @param search 要搜索的字段
     * @param keyword 搜索关键词
     * @param page 页码
     * @param size 页面大小
     * @return 页面
     */
    public Page<User> getAllUsers(String search, String keyword, int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        if (keyword.isEmpty() || search.equals("all"))
            return userRepository.findAll(pageable);
        else if (search.equals("username"))
            return userRepository.findAllByUsernameContaining(keyword, pageable);
        else if (search.equals("id"))
            return userRepository.findAllByIdContaining(keyword, pageable);
        else if (search.equals("phoneNumber"))
            return userRepository.findAllByPhoneNumberContaining(keyword, pageable);
        return userRepository.findAll(pageable);
    }

    /** 更改密码 */
    public void changePassword(User user, String newPassword) {
        user.setPassword(newPassword);
        userRepository.save(user);
    }

    /** 更改手机号 */
    public void changePhoneNumber(User user, String phoneNumber) {
        user.setPhoneNumber(phoneNumber);
        userRepository.save(user);
    }
}
